package top.java.multithreading;


import java.util.concurrent.*;

/**
 *        多线程的创建      方式四：线程池       --JDK 5.0新增
 *
 *        1.提供指定线程数量的线程池
 *          1.1 将线程池对象 强转为 ThreadPoolExecutor类型对象
 *          1.2 设置线程池参数
 *        2.执行指定的线程操作，需要提供实现Runnable 或 Callable接口实现类的对象
 *          2.1 如实现的是Callable接口且需要返回值，则用Future类型对象接收，并调用该对象get()方法
 *        3.关闭连接池
 *
 *        使用线程池的好处：
 *          提高响应速度（减少了创建新线程的时间）
 *          降低资源消耗（重复利用线程池中线程，不需要每次都创建）
 *          便于线程管理
 *
 *    Executors：线程池的工具类通过调用方法返回不同类型的线程池对象。
 *
 *    public static ExecutorService newCachedThreadPool()
 *    线程数量随着任务增加而增加，如果线程任务执行完毕且空闲了一段时间则会被回收掉。
 *
 *    public static ExecutorService newFixedThreadPool (int nThreads)
 *    创建固定线程数量的线程池，如果某个线程因为执行异常而结束，那么线程池会补充一个新线程替代它。
 *
 *    public static ExecutorService newSingleThreadExecutor ()
 *    创建只有一个线程的线程池对象，如果该线程出现异常而结束，那么线程池会补充一个新线程。
 *
 *    public static ScheduledExecutorService newScheduledThreadPool (int corePoolSize)
 *    创建一个线程池，可以实现在给定的延迟后运行任务，或者定期执行任务。
 *
 *    注意：Executors的底层其实也是基于线程池的实现类ThreadPoolExecutor创建线程池对象的。
 *
 *    Executors工具类底层是基于什么方式实现的线程池对象？
 *      线程池ExecutorService的实现类：ThreadPoolExecutor
 *
 *    Executors是否适合做大型互联网场景的线程池方案？
 *      不合适。
 *      建议使用ThreadPoolExecutor来指定线程池参数，这样可以明确线程池的运行规则，规避资源耗尽的风险。
 *
 *    大型并发系统环境中使用Executors如果不注意可能会出现系统风险：
 *
 *    newFixedThreadPool(int nThreads)
 *    newSingleThreadExecutor()
 *   这两种创建方式允许请求的任务队列长度是Integer.MAX_VALUE，可能出现OOM错误（java.lang.OutOfMemoryError）
 *
 *
 *    newCachedThreadPool()
 *    newScheduledThreadPool(int corePoolSize)
 *    这两种方式创建的线程数量最大上限是Integer.MAX_VALUE，线程数可能会随着任务1:1增长，也可能出现OOM错误
 *
 */

public class ThreadTest12 {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
        service1.setCorePoolSize(15);       //设置核心池的大小
        service1.setMaximumPoolSize(15);    //设置最大线程数

        service.execute(new SumThread());          //适用于Runnable
        Future submit = service.submit(new HumThread());//适用于Callable
        Object o = null;
        try {
            o = submit.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("总和为" + o);

        service.shutdown();         //关闭连接池
    }
}

class SumThread implements Runnable {

    @Override
    public void run() {

    }
}

class HumThread implements Callable {

    @Override
    public Object call() throws Exception {
        int num = 0;
        for (int i = 0;i <= 100;i++) {
            if (i % 2 == 0) {
                System.out.println(i);
                num += i;
            }
        }
        return num;
    }
}
